<template>
  <div id="canvas-container">
    <canvas id="my-canvas" ref="my-canvas"></canvas>
  </div>

</template>

<script>
import * as THREE from "three";
import * as d3geo from "d3-geo";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
// import {Geometry} from 'three/examples/jsm/deprecated/Geometry';
import chinaJson from "../assets/geo.json";

console.log(chinaJson)
export default {
  name: "GeoJsonDemo",
  data() {
    return {
      scene: null,
      map: null,
      renderer: null,
      camera: null,
      axisHelper: null,
      mouse: null,
      raycaster: null,
      composer: null,
      outlinePass: null,
      renderPass: null
    }
  },
  mounted() {
    // 初始化3D环境
    this.initEnvironment()
    // 构建光照系统
    this.buildLightSystem()
    // 构建辅助系统
    this.buildAuxSystem()
    this.initMap()
    this.renderer.render(this.scene, this.camera);

    // 渲染场景
    let animate = () => {
      requestAnimationFrame(animate);
      //渲染外发光
      this.renderer.render(this.scene, this.camera);
      // if (this.composer) {
      //   this.composer.render()
      // }
    };
    animate();

    //获取鼠标坐标
    this.mouse = new THREE.Vector2();
    this.raycaster = new THREE.Raycaster();
    window.addEventListener("click", this.onMouseClick);
  },
  methods: {
    // 初始化3D环境
    initEnvironment() {
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0)
      // 建一个空对象存放对象
      this.map = new THREE.Object3D()
      this.map.position.set(30, -10, 0)
      // 设置相机参数
      this.setCamera();
      // 初始化
      this.renderer = new THREE.WebGLRenderer({
        alpha: true,
        canvas: this.$refs["my-canvas"],
        antialias: true //抗锯齿
      })
      this.renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      this.renderer.setPixelRatio(window.devicePixelRatio)
      // this.renderer.setSize(window.innerWidth, window.innerHeight - 10)
      this.renderer.setSize(800, 500)
      document.addEventListener('mousemove', this.onDocumentMouseMove, false)
      // window.addEventListener('resize', this.onWindowResize, false)
    },
    setCamera() {
      // this.camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 10000);
      this.camera = new THREE.PerspectiveCamera(90, 800 / 500, 1, 10000);
      this.camera.position.set(50, 30, 60);
      this.camera.lookAt(0, 0, 0);
    },
    // 构建辅助系统: 网格和坐标
    buildAuxSystem() {
      // let axisHelper = new THREE.AxesHelper(2000)
      // this.scene.add(axisHelper)
      // let gridHelper = new THREE.GridHelper(600, 60)
      // this.scene.add(gridHelper)

      let controls = new OrbitControls(this.camera, this.renderer.domElement)
      let that = this
      controls.addEventListener('change', function () {
        that.renderer.render(that.scene, that.camera)
      });//监听鼠标、键盘事件
      controls.enableDamping = true
      controls.dampingFactor = 0.25
      controls.rotateSpeed = 0.35
    },
    // 光照系统
    buildLightSystem() {
      let directionalLight = new THREE.DirectionalLight(0xffffff, 1.1);
      directionalLight.position.set(300, 1000, 500);
      directionalLight.target.position.set(0, 0, 0);
      directionalLight.castShadow = true;

      let d = 300;
      const fov = 45 //拍摄距离  视野角值越大，场景中的物体越小
      const near = 1 //相机离视体积最近的距离
      const far = 1000//相机离视体积最远的距离
      const aspect = window.innerWidth / window.innerHeight; //纵横比
      directionalLight.shadow.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      directionalLight.shadow.bias = 0.0001;
      directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024;
      this.scene.add(directionalLight)

      let light = new THREE.AmbientLight(0xffffff, 0.6)
      this.scene.add(light)

    },
    // 根据浏览器窗口变化动态更新尺寸
    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    onDocumentMouseMove(event) {
      event.preventDefault();
    },
    parseGeoJson(geoJson, projection, z) {
      // 遍历省份构建模型
      geoJson.features.forEach(elem => {
        // 新建一个省份容器：用来存放省份对应的模型和轮廓线
        const province = new THREE.Object3D()
        const coordinates = elem.geometry.coordinates
        coordinates.forEach(multiPolygon => {
          multiPolygon.forEach(polygon => {
            // 这里的坐标要做2次使用：1次用来构建模型，1次用来构建轮廓线
            const shape = new THREE.Shape();
            const lineMaterial = new THREE.LineBasicMaterial({color: 0xffffff});
            let vertices = [];
            const linGeometry = new THREE.BufferGeometry();
            for (let i = 0; i < polygon.length; i++) {
              const [x, y] = projection(polygon[i]);
              if (i === 0) {
                shape.moveTo(x, -y);
              }
              shape.lineTo(x, -y);
              vertices.push(x, -y, 1.01 + z);
              linGeometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
            }
            const extrudeSettings = {
              depth: 1,
              bevelEnabled: false
            };
            const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
            const material = new THREE.MeshBasicMaterial({color: '#d13a34', transparent: true, opacity: 0.6});
            const mesh = new THREE.Mesh(geometry, material);
            mesh.position.set(0, 0, z);
            const line = new THREE.Line(linGeometry, lineMaterial);
            province.add(mesh);
            province.add(line);
          })
        })
        // 将geojson的properties放到模型中，后面会用到
        province.properties = elem.properties;
        if (elem.properties.centroid) {
          const [x, y] = projection(elem.properties.centroid);
          province.properties._centroid = [x, y]
        }
        this.map.add(province);
      })
    }
    ,
    initMap() {
      // d3-geo转化坐标
      const projection = d3geo.geoMercator().center([104.0596, 30.4629]).scale(800000).translate([0, 0]);
      this.parseGeoJson(chinaJson, projection, -20);
      this.parseGeoJson(chinaJson, projection, -40);
      this.parseGeoJson(chinaJson, projection, 0);
      this.parseGeoJson(chinaJson, projection, 20);
      this.parseGeoJson(chinaJson, projection, 40);
      this.scene.add(this.map);
    },
    // 改变对象材质属性
    changeMaterial(object) {
      object.material = new THREE.MeshLambertMaterial({
        color: 0xffffff * Math.random(),
        transparent: !object.material.transparent,
        opacity: 0.8
      });
    },
    onMouseClick(event) {
      // this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      // this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

      this.mouse.x = (event.clientX / 800) * 2 - 1;
      this.mouse.y = -(event.clientY / 500) * 2 + 1;

      this.raycaster.setFromCamera(this.mouse, this.camera);
      const intersects = this.raycaster.intersectObjects(this.scene.children);
      console.log(intersects)
      if (intersects.length > 0) {
        console.log("click")
        // 获取选中最近的 Mesh 对象
        if (intersects[0].object instanceof THREE.Mesh) {
          let selectObject = intersects[0].object;
          this.changeMaterial(selectObject);
        }
      }
      // this.renderer.renderer()
      // console.log(intersects);
    },
  }
}
</script>

<style scoped>
#my-canvas {
  width: 1000px;
  height: 900px;
}
</style>
